package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB // 一个连接池对象

func initDB() (err error) {
	dsn := "root:123456@tcp(10.10.10.101:33306)/test_demo"
	db, err = sql.Open("mysql", dsn)
	if err != nil { // dsn格式不正确
		fmt.Printf("dsn: %s invalid, err: %v\n", dsn, err)
		return
	}
	err = db.Ping()
	if err != nil { // 连接不上数据库,说明用户名密码错误
		fmt.Printf("open %s failed, err: %v\n", dsn, err)
		return
	}
	// 设置数据库连接池最大连接数
	db.SetMaxOpenConns(10)
	return
}

type user struct {
	id   int
	name string
	age  int
}

func transaction() {
	// 开启事务
	tx, err := db.Begin()
	if err != nil {
		fmt.Printf("begin failed, err: %v\n", err)
		return
	}
	// 多个sql操作
	sqlStr1 := `update user set age= age-5 where id = 5`
	//sqlStr2 := `update user set age= age+5 where id = 6`

	// 模拟后面一条sql执行出错
	sqlStr2 := `update xxxxxxxxxx set age= age+5 where id = 6`

	_, err = tx.Exec(sqlStr1)
	if err != nil {
		// 回滚
		tx.Rollback()
		fmt.Println("sql1出错了")
	}
	_, err = tx.Exec(sqlStr2)
	if err != nil {
		// 回滚
		tx.Rollback()
		fmt.Println("sql2出错了")
	}
	// 两个sql都执行成功,就提交事务, 提交事务也会有可能出错
	err = tx.Commit()
	if err != nil {
		tx.Rollback()
		fmt.Println("提交事务出错了")
		return
	}
	fmt.Println("事务执行结束")
}

func main() {
	err := initDB()
	if err != nil {
		fmt.Printf("init DB failed, err: %v\n", err)
		return
	}
	fmt.Println("连接数据库成功")

	transaction()
}
